#ifndef __GVJSERVER_HEADER
#define __GVJSERVER_HEADER

#include "gvj.h"
#include "epoll_data.h"
#include "socket_recv_buff.h"
#include "socket_send_buff.h"
#include "pipe_recv_buff.h"
#include "pipe_send_buff.h"
#include "request_filter.h"
#include "proxy_starter.h"
#include "listen_deserialize.h"
#include "listen_serialize.h"
#include "oj.h"
#include "poj.h"
#include "hdu.h"

#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <time.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/epoll.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#include <utility>
#include <string>
#include <vector>
#include <queue>
#include <map>

class GvjServer {
private:
	typedef key_t msg_key;
private:
	// 协议Header大小，字段大小
	static const int HEADER_SIZE;
	static const int FIELD_SIZE;
	// 协议Header大小，字段大小
	
	// 描述服务器端需要的成员变量
	// 监听socket描述符;监听socket的地址结构;server_addr结构长度
	int listen_fd;
	struct sockaddr_in server_addr;
	socklen_t server_addr_len;
	// 描述服务器端需要的成员变量
	
	// 描述客户端需要的成员变量
	// 客户端socket描述符;客户端socket的地址结构;client_addr结构长度
	int client_fd;
	struct sockaddr_in client_addr;
	socklen_t client_addr_len;
	// 描述客户端需要的成员变量

	// 描述epoll需要的成员变量
	// epoll句柄;辅助变量;保存就绪事件的结构体数组指针
	int ep_fd;
	struct epoll_event ev;
	struct epoll_event *ready_evs;
	// 描述epoll需要的成员变量

	// 代理进程启动器，过滤器，反序列化，序列化（仿函数）
	ProxyStarter 			proxy_starter;
	RequestFilter 			request_filter;
	ListenDeserialize	 	deserialize;
	ListenSerialize		  	serialize;
	// 代理进程启动器，过滤器，反序列化，序列化（仿函数）

	// 根据OJ名称查询相应的信息
	// 1. 相应代理进程的pipe(两条管道)
	// 2. OJ对象
	// 3. out_pipe的字节流发送列表
	// 4. out_pipe是否在epoll中注册
	std::map<std::string, std::pair<int*, int*> > 		map_pipe;
	std::map<std::string, OJ*> 							map_oj_obj;
	std::map<std::string, std::queue<PipeSendBuff*>* >	map_que;
	std::map<std::string, bool>							map_register;
	// 根据OJ名称查询相应的信息

	// 与日志进程通信的消息队列的相关信息
	int msg_id;
	static const msg_key  MSG_KEY;
	static const int MSG_CREAT_FLAG;
	static const int MSG_TEST_FLAG;
	static const int MSG_EXCL_FLAG;
	// 与日志进程通信的消息队列的相关信息
	
private:
	int listen_socket_ready();
	int client_socket_recv_ready(EpollData *ep_data);
	int client_socket_send_ready(EpollData *ep_data);
	int pipe_recv_ready(EpollData *ep_data);
	int pipe_send_ready(EpollData *ep_data);
	void check_map_list();
	
	void set_sockaddr_in(struct sockaddr_in *sa);
	int close_socket(int fd, EpollData *ep_data, Buff *buff);
	void create_proxy_process(const char *oj, const char *cookie_dir);

public:
	// GvjServer的入口，根据配置信息初始化自身，fork代理进程等
	int main_process(std::vector<std::string> oj);
	// GvjServer的监听流程
	int listen_process();
};

#endif // __GVJSERVER_HEADER
